#! /usr/bin/python3
# -*-coding: utf-8-*-
import logzero
import struct
from collections import namedtuple


KS833_OutputStatus = namedtuple(
    "KS833_OutputStatus", "Ua_Rms Ub_Rms Uc_Rms Ua_Ang Ub_Ang Uc_Ang Ia_Rms Ib_Rms Ic_Rms Ia_Ang Ib_Ang Ic_Ang"
)


class KS833_PACK_GEN:
    def __init__(self, logger=logzero.logger):
        self.rms_us = [44] * 3
        self.rms_is = [1] * 3
        self.angle_us = [0, 240, 120]
        self.angle_is = [0, 240, 120]
        self.freq = 50
        self.phase_num = 0b111111
        self.logger = logger

    def get_status(self):
        """In python3.4 Parameters expansion works only in function arguments, not inside tuples
        https://stackoverflow.com/questions/34766677/python-splat-unpack-operator-in-python-cannot-be-used-in-an-expression/34767282
        https://www.python.org/dev/peps/pep-0448/
        """
        return KS833_OutputStatus(
            self.rms_us[0],
            self.rms_us[1],
            self.rms_us[2],
            self.angle_us[0],
            self.angle_us[1],
            self.angle_us[2],
            self.rms_is[0],
            self.rms_is[1],
            self.rms_is[2],
            self.angle_is[0],
            self.angle_is[1],
            self.angle_is[2],
        )

    def float_2_bytes(self, value):
        return bytearray(struct.pack("f", value))

    def pack_connect(self):
        """开始连接"""
        return bytearray((0x7E, 0x60, 0x00, 0x00, 0xFF, 0x3F))

    def pack_shutdown_output(self):
        """关闭输出连接"""
        return bytearray((0x7E, 0xB5, 0x00, 0x00, 0xFF))

    def pack_disconnect(self):
        """断开连接"""
        return bytearray((0x7E, 0x70, 0x00, 0x00, 0xFF))

    def get_range_para_i(self, iv):
        """电流档位获取 25 10 5 1 0.1"""
        iv /= 1.2
        if iv <= 0.1:
            return 4
        elif iv <= 1:
            return 3
        elif iv <= 5:
            return 2
        elif iv <= 10:
            return 1
        else:
            return 0

    def get_range_para_u(self, uv):
        """电压档位获取 750 300 100 30 10"""
        uv /= 1.2
        if uv <= 10:
            return 4
        elif uv <= 30:
            return 3
        elif uv <= 100:
            return 2
        elif uv <= 300:
            return 1
        else:
            return 0

    def is_switch_range(self, output_status: KS833_OutputStatus):
        old_ranges_u = [self.get_range_para_u(i) for i in self.rms_us]
        old_ranges_i = [self.get_range_para_i(i) for i in self.rms_is]
        new_ranges_u = [
            self.get_range_para_u(i) for i in (output_status.Ua_Rms, output_status.Ub_Rms, output_status.Uc_Rms)
        ]
        new_ranges_i = [
            self.get_range_para_i(i) for i in (output_status.Ia_Rms, output_status.Ib_Rms, output_status.Ic_Rms)
        ]
        if old_ranges_u == new_ranges_u and old_ranges_i == new_ranges_i:
            return False
        return True

    def conf_output_status(self, output_status: KS833_OutputStatus):
        self.rms_us = [output_status.Ua_Rms, output_status.Ub_Rms, output_status.Uc_Rms]
        self.rms_is = [output_status.Ia_Rms, output_status.Ib_Rms, output_status.Ic_Rms]
        self.angle_us = [output_status.Ua_Ang, output_status.Ub_Ang, output_status.Uc_Ang]
        self.angle_is = [output_status.Ia_Ang, output_status.Ib_Ang, output_status.Ic_Ang]

    def pack_start_output(self):
        """开始输出
        00 ~ 03 head          -->  7E B0 00 3B
        04 ~ 04 phase_num     -->  3F
        05 ~ 07 volte range   -->  01 01 01
        08 ~ 10 current range -->  01 01 01
        11 ~ 14 ua rms        -->  00 00 30 42  44.0
        15 ~ 18 ua angle      -->  00 00 00 00  0.0
        19 ~ 22 ub rms        -->  00 00 30 42  44.0
        23 ~ 27 ub angle      -->  00 00 70 43  240.0
        27 ~ 30 uc rms        -->  00 00 30 42  44.0
        31 ~ 34 uc angle      -->  00 00 F0 42  120.0
        35 ~ 38 ia rms        -->  00 00 80 3F  1.0
        39 ~ 42 ia angle      -->  00 00 00 00  0.0
        43 ~ 46 ib rms        -->  00 00 80 3F  1.0
        47 ~ 50 ib angle      -->  00 00 70 43  240.0
        51 ~ 54 ic rms        -->  00 00 80 3F  1.0
        55 ~ 58 ic angle      -->  00 00 F0 42  120.0
        59 ~ 62 freq          -->  00 00 48 42  50.00
        63 ~ 63 tail          -->  FF
        """
        data = [0] * 64
        # head
        data[0:4] = (0x7E, 0xB0, 0x00, 0x3B)
        # phase para
        data[4] = self.phase_num
        # range para u
        data[5] = self.get_range_para_u(self.rms_us[0])
        data[6] = self.get_range_para_u(self.rms_us[1])
        data[7] = self.get_range_para_u(self.rms_us[2])
        # range para i
        data[8] = self.get_range_para_i(self.rms_is[0])
        data[9] = self.get_range_para_i(self.rms_is[1])
        data[10] = self.get_range_para_i(self.rms_is[2])
        # ui data
        for i, uaia in enumerate(zip(self.rms_us, self.angle_us, self.rms_is, self.angle_is)):
            rms_u, angle_u, rms_i, angle_i = uaia
            data[11 + i * 8 : 11 + i * 8 + 4] = self.float_2_bytes(rms_u)
            data[15 + i * 8 : 15 + i * 8 + 4] = self.float_2_bytes(angle_u)
            data[35 + i * 8 : 35 + i * 8 + 4] = self.float_2_bytes(rms_i)
            data[39 + i * 8 : 39 + i * 8 + 4] = self.float_2_bytes(angle_i)
        data[59:63] = self.float_2_bytes(self.freq)
        data[63] = 0xFF
        return bytearray(data)

    def pack_adjust_output(self):
        """ 调整输出
        00 ~ 03 head          -->  7E B1 00 35
        04 ~ 07 ua rms        -->  00 00 DC 42  110.0
        08 ~ 11 ua angle      -->  00 00 00 00  0.0
        12 ~ 15 ub rms        -->  00 00 DC 42  110.0
        16 ~ 19 ub angle      -->  00 00 70 43  240.0
        20 ~ 23 uc rms        -->  00 00 DC 42  110.0
        24 ~ 27 uc angle      -->  00 00 F0 42  120.0
        28 ~ 31 ia rms        -->  00 00 20 40  2.5
        32 ~ 35 ia angle      -->  00 00 96 43  300.0
        36 ~ 39 ib rms        -->  00 00 20 40  2.5
        40 ~ 43 ib angle      -->  00 00 07 44  540.0
        44 ~ 47 ic rms        -->  00 00 20 40  2.5
        48 ~ 51 ic angle      -->  00 00 D2 43  420.0
        52 ~ 55 freq          -->  00 00 48 42  50.00
        56 ~ 57 tail          -->  00 FF
        """
        data = [0] * 58
        # head
        data[0:4] = (0x7E, 0xB1, 0x00, 0x35)
        # ui data
        for i, uaia in enumerate(zip(self.rms_us, self.angle_us, self.rms_is, self.angle_is)):
            rms_u, angle_u, rms_i, angle_i = uaia
            data[4 + i * 8 : 4 + i * 8 + 4] = self.float_2_bytes(rms_u)
            data[8 + i * 8 : 8 + i * 8 + 4] = self.float_2_bytes(angle_u)
            data[28 + i * 8 : 28 + i * 8 + 4] = self.float_2_bytes(rms_i)
            data[32 + i * 8 : 32 + i * 8 + 4] = self.float_2_bytes(angle_i)
        data[52:56] = self.float_2_bytes(self.freq)
        data[56:58] = (0x00, 0xFF)
        return bytearray(data)


# ############################################# 5A ##############################################
# [11:52:29.144]收←◆7E 60 00 00 FF 3F
# [11:52:31.147]收←◆7E B0 00 3B 3F 01 01 01 01 01 01 00 00 30 42 00 00 00 00 00 00 30 42 00 00 70 43 00 00 30 42 00 00 F0 42 00 00 80 3F 00 00 00 00 00 00 80 3F 00 00 70 43 00 00 80 3F 00 00 F0 42 00 00 48 42 FF
#                    7E B0 00 3B 3F 02 02 02 02 02 02 00 00 30 42 00 00 00 00 00 00 30 42 00 00 70 43 00 00 30 42 00 00 F0 42 00 00 80 3F 00 00 00 00 00 00 80 3F 00 00 70 43 00 00 80 3F 00 00 F0 42 00 00 48 42 FF

# [11:52:46.159]收←◆7E B1 00 35 00 00 DC 42 00 00 00 00 00 00 DC 42 00 00 70 43 00 00 DC 42 00 00 F0 42 00 00 20 40 00 00 96 43 00 00 20 40 00 00 07 44 00 00 20 40 00 00 D2 43 00 00 48 42 00 FF
#                   7E B1 00 35 00 00 DC 42 00 00 00 00 00 00 DC 42 00 00 70 43 00 00 DC 42 00 00 F0 42 00 00 20 40 00 00 96 43 00 00 20 40 00 00 07 44 00 00 20 40 00 00 D2 43 00 00 48 42 00 FF

# [11:52:58.164]收←◆7E B1 00 35 00 00 5C 43 00 00 00 00 00 00 5C 43 00 00 70 43 00 00 5C 43 00 00 F0 42 00 00 A0 40 00 00 96 43 00 00 A0 40 00 00 07 44 00 00 A0 40 00 00 D2 43 00 00 48 42 00 FF
#                   7E B1 00 35 00 00 5C 43 00 00 00 00 00 00 5C 43 00 00 70 43 00 00 5C 43 00 00 F0 42 00 00 A0 40 00 00 96 43 00 00 A0 40 00 00 07 44 00 00 A0 40 00 00 D2 43 00 00 48 42 00 FF

# [11:53:10.169]收←◆7E B1 00 35 00 00 84 43 00 00 00 00 00 00 84 43 00 00 70 43 00 00 84 43 00 00 F0 42 00 00 C0 40 00 00 96 43 00 00 C0 40 00 00 07 44 00 00 C0 40 00 00 D2 43 00 00 48 42 00 FF
#                   7E B1 00 35 00 00 84 43 00 00 00 00 00 00 84 43 00 00 70 43 00 00 84 43 00 00 F0 42 00 00 C0 40 00 00 96 43 00 00 C0 40 00 00 07 44 00 00 C0 40 00 00 D2 43 00 00 48 42 00 FF

# [11:53:22.177]收←◆7E B1 00 35 00 00 5C 43 00 00 00 00 00 00 5C 43 00 00 70 43 00 00 5C 43 00 00 F0 42 00 00 20 40 00 00 96 43 00 00 20 40 00 00 07 44 00 00 20 40 00 00 D2 43 00 00 48 42 00 FF
#                   7E B1 00 35 00 00 5C 43 00 00 00 00 00 00 5C 43 00 00 70 43 00 00 5C 43 00 00 F0 42 00 00 20 40 00 00 96 43 00 00 20 40 00 00 07 44 00 00 20 40 00 00 D2 43 00 00 48 42 00 FF
# [11:53:34.181]收←◆7E B5 00 00 FF
# [11:53:37.183]收←◆7E 70 00 00 FF
# ##############################################################################################

# ############################################# 1A ##############################################
# [15:03:55.195]收←◆7E 60 00 00 FF 3F
# [15:03:57.195]收←◆7E B0 00 3B 3F 01 01 01 01 01 01 00 00 30 42 00 00 00 00 00 00 30 42 00 00 70 43 00 00 30 42 00 00 F0 42 CD CC 4C 3E 00 00 00 00 CD CC 4C 3E 00 00 70 43 CD CC 4C 3E 00 00 F0 42 00 00 48 42 FF
# [15:04:12.202]收←◆7E B1 00 35 00 00 DC 42 00 00 00 00 00 00 DC 42 00 00 70 43 00 00 DC 42 00 00 F0 42 00 00 00 3F 00 00 96 43 00 00 00 3F 00 00 07 44 00 00 00 3F 00 00 D2 43 00 00 48 42 00 FF
# [15:04:24.208]收←◆7E B1 00 35 00 00 5C 43 00 00 00 00 00 00 5C 43 00 00 70 43 00 00 5C 43 00 00 F0 42 00 00 80 3F 00 00 96 43 00 00 80 3F 00 00 07 44 00 00 80 3F 00 00 D2 43 00 00 48 42 00 FF
# [15:04:36.213]收←◆7E B1 00 35 00 00 84 43 00 00 00 00 00 00 84 43 00 00 70 43 00 00 84 43 00 00 F0 42 9A 99 99 3F 00 00 96 43 9A 99 99 3F 00 00 07 44 9A 99 99 3F 00 00 D2 43 00 00 48 42 00 FF
# [15:04:48.218]收←◆7E B1 00 35 00 00 5C 43 00 00 00 00 00 00 5C 43 00 00 70 43 00 00 5C 43 00 00 F0 42 00 00 00 3F 00 00 96 43 00 00 00 3F 00 00 07 44 00 00 00 3F 00 00 D2 43 00 00 48 42 00 FF
# [15:05:00.221]收←◆7E B5 00 00 FF
# [15:05:03.223]收←◆7E 70 00 00 FF
# ##############################################################################################

if __name__ == "__main__":
    from helpers.mengy_bytes_helper import bytesPuttyPrint

    kpg = KS833_PACK_GEN()
    bytesPuttyPrint(kpg.pack_connect())
    bytesPuttyPrint(kpg.pack_disconnect())
    bytesPuttyPrint(kpg.pack_shutdown_output())
    bytesPuttyPrint(kpg.pack_start_output())

    kpg.rms_us = [220 * 0.5] * 3
    kpg.rms_is = [5 * 0.5] * 3
    kpg.angle_is = [i + 300 for i in kpg.angle_us]
    bytesPuttyPrint(kpg.pack_adjust_output())

    kpg.rms_us = [220] * 3
    kpg.rms_is = [5] * 3
    bytesPuttyPrint(kpg.pack_adjust_output())

    kpg.rms_us = [220 * 1.0] * 3
    kpg.rms_is = [5 * 0.5] * 3
    bytesPuttyPrint(kpg.pack_adjust_output())
